package com.sqss;

import com.sun.istack.internal.NotNull;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;


/**
 * 数据库删除数据的理念, 一般来说都是不直接删除某一个数据表格中的数据, 通过增加一个字段来标识该字段是否是有效的的
 * 比如说: User( id , name , age , birthday , address , valid) 其中valid是用来标识该数据是否已经被删除了的,
 */
public class SQSS {

    // 根据制定的字段来更新 SQSS对象
    // 如果args的长度为零, 默认更具对象的id值来更新

    /**
     * @param sqss SQSS 子类的对象
     * @param args 指定更新的字段, 如果不指定,则更新除id以外的所有字段对应的值,如果指定更新的字段, 则根据id来更新指定的字段,更新的值从sqss对象中传递过来
     * @return
     */
    public static int update(SQSS sqss, String... args) {

        int num = 0;
        List<Object> objects = new ArrayList<>();
        if (sqss == null) {
            throw new NullPointerException("sqss could not be null ");
        }
        StringBuffer sb = new StringBuffer("UPDATE ");

        String sql = "";
        System.out.println("sqss " + sqss.getClass().getName());
        try {
            Class<?> clazz = sqss.getClass();

            // 指定更新的表
            // 这里是获取类名, 然后将类名转为小写, 比如说 models 类在 models.Student ,
            //那么 class.getSimpleName() //返回则为Student => .toLowerCase => student
            sb.append(clazz.getSimpleName().toLowerCase());
            // 这里是构造 sql 语句 将 "(空格) SET (空格)" 添加
            sb.append(String.valueOf(" SET "));

            //根据字段更新
            if (args.length == 0) {
                // 如果传入的参数为空
                // 则更新除id意外的全部字段的值
                // 故而在更新就要判断要更新字段值的有效性
                // 获取 所有属性字段
                Field[] fields = clazz.getDeclaredFields();

                for (Field f : fields) {
                    System.out.println("f " + f.getName());
                    // 如果 获取到字段是id, 则跳过本次
                    if (f.getName().equals("id")) {
                        continue;
                    }
                    // 构造sql ,比如我传入的Student => name
                    //  f.getName() == "name"
                    // sb.append(" " + " name " + " = ? " )
                    sb.append(String.valueOf(" " + f.getName() + " = ? ,"));
                    // 设置f 字段是可以访问的
                    f.setAccessible(true);
                    // 通过传入的对象来获取相应字段的值
                    //  sqss ==> Student  && f.getName() == "name"
                    // 那么 f.get(sqss) // 获取的则是 Student.name 字段的值, 传入的对象是sqss
                    // Student 必须继承 SQSS
                    Object value = f.get(sqss);
                    // 将获取到的值传入查询列表
                    objects.add(value);
                }

            } else {
                // 如果指定了更新的字段....
                // 不定长参数传入的其实是一个数组
                // 这里根据传入参数的长度来判断更新的字段
                for (int i = 0; i < args.length; i++) {
                    // 不能更新指定的ID
                    // 遇到id 跳过
                    if (args[i].equals("id") || args[i].equals("ID")) {
                        continue;
                    }
                    sb.append(String.valueOf(" " + args[i].toLowerCase() + " = ? ,"));
                    Field field = clazz.getDeclaredField(args[i]);
                    field.setAccessible(true);
                    Object value = field.get(sqss);
                    objects.add(value);
                }
            }
            sql = sql + sb.substring(0, sb.toString().length() - 1);
            // 构造条件
            // 获取id 字段的值
            sql += " WHERE id = ? ";
            Field id = clazz.getDeclaredField("id");
            id.setAccessible(true);
            Object value = id.get(sqss);
            Integer key = (Integer) value;
            // 如果没有指定id,则本次更新不能成功
            if (key == 0) {
                throw new Exception("key must not be zero ");
            }
            objects.add(value);
            System.out.println("Sql " + sql);
            System.out.println(objects);

            // 调用 update
            int update = BaseConn.update(sql, objects);
            System.out.println("update " + update);

            //
            System.out.println(clazz.getSimpleName().toLowerCase());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static <SQSS> List<SQSS> read(SQSS sqss, String... args) {
        List<SQSS> lists = (List<SQSS>) new ArrayList<SQSS>();

        String sql = "";
        Class<? extends SQSS> clazz = (Class<? extends SQSS>) sqss.getClass();
        StringBuffer sb = new StringBuffer("SELECT ");
        Field[] fields = clazz.getDeclaredFields();

        for (int i = 0; i < fields.length; i++) {
            if (i == fields.length - 1) {
                sb.append(String.valueOf(fields[i].getName() + " "));

            } else {
                sb.append(String.valueOf(fields[i].getName() + " , "));

            }

        }
        sb.append(String.valueOf(" FROM " + clazz.getSimpleName().toLowerCase() + " WHERE "));

        // 参数列表
        List<Object> objects = new ArrayList<>();
        // 如果参数的长度为空
        if (args.length == 0) {
            sb.append(" id = ? ");
            try {
                Field field = clazz.getDeclaredField("id");
                field.setAccessible(true);
                objects.add(field.get(sqss));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // 如果查询参数的字段不为空,
            for (int i = 0; i < args.length; i++) {
                if (i == args.length - 1) {
                    try {
                        Field f = clazz.getDeclaredField(args[i]);
                        f.setAccessible(true);
                        objects.add(f.get(sqss));
                        sb.append(" " + f.getName() + " = ?");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }


                } else {
                    Field f = null;
                    try {
                        f = clazz.getDeclaredField(args[i]);
                        f.setAccessible(true);
                        objects.add(f.get(sqss));
                        sb.append(String.valueOf(" " + f.getName() + " = ? AND "));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }
        }
        sql = sb.toString();
        System.out.println("sql is " + sql + "  " + objects);
        return BaseConn.query(sql, objects, clazz);


    }

    public static int delete(SQSS sqss, String... args) {
        int num = 0;
        return num;
    }

    // 向数据库中插入数据,
    // sqss 指向的对象必须是有效的...
    // 返回插入数据的id
    public static int insert(@NotNull SQSS sqss) {
        int num = 0;
        List<Object> objects = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        StringBuffer values = new StringBuffer(" values (");
        String sql = "";
        Class<? extends SQSS> clazz = sqss.getClass();
        Field[] fields = clazz.getDeclaredFields();
        sb.append(String.valueOf("INSERT INTO " + clazz.getSimpleName().toLowerCase() + " ( "));
        for (Field f : fields) {
            if (f.getName().equals("id") || f.getName().equals("ID")) {
                continue;
            }
            f.setAccessible(true);
            Object value = null;
            try {
                value = f.get(sqss);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            values.append(String.valueOf(" ? ,"));
            objects.add(value);
            sb.append(f.getName() + " ,");
        }
        sql = sb.substring(0, sb.length() - 1);
        sql += " ) ";
        sql += values.substring(0, values.length() - 1) + " ) ";
        System.out.println("INSERT " + sql);
        num = BaseConn.insert(sql, objects);
        try {
            Field id = clazz.getDeclaredField("id");
            id.setAccessible(true);
            id.set(sqss, num);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return num;
    }
}
